package controller

import (
	"errors"
	"ginfast/api/system/dto"
	"ginfast/api/system/model"
	"ginfast/api/system/service"
	"ginfast/configs"
	"ginfast/middleware"
	"ginfast/pkg/dao"
	"ginfast/pkg/gctx"
	"ginfast/util"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// User
type User struct {
}

// ListHandler 用户列表
func (User) ListHandler(c *gin.Context) {
	var p dto.Where
	if err := c.ShouldBind(&p); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	t := middleware.GetUserToken(c)
	if t.UserName != model.SysUserName {
		p.CreatedBy = t.UserName
	}
	var data []model.SysUser
	total, _ := p.DbModelWhere(&model.SysUser{}).Preload("Dept").Find(&data)
	gctx.JSONWrite(gin.H{"data": data, "total": total}, c)
}

// MenuHandler
func (User) MenuHandler(c *gin.Context) {
	t := middleware.GetUserToken(c)
	menulist, permissions := service.SysMenuRouter(t.RoleID)
	gctx.JSONWriteData(gin.H{"menuList": menulist, "permissions": permissions}, c)
}

type userRole struct {
	ID   uint   `json:"id"`
	Name string `json:"name"`
}

type userPost struct {
	ID   uint   `json:"postId"`
	Name string `json:"postName"`
}

// ParamsHandler
func (User) ParamsHandler(c *gin.Context) {
	t := middleware.GetUserToken(c)
	var roles []userRole
	dao.DB().Model(&model.SysRole{}).Where("created_by = ?", t.UserName).Scan(&roles)
	var posts []userPost
	dao.DB().Model(&model.SysPost{}).Scan(&posts)
	gctx.JSONWriteData(gin.H{"roleList": roles, "posts": posts}, c)
}

// GetHandler
func (User) GetHandler(c *gin.Context) {
	queryId := gctx.ParamUInt(c, "id")
	var user model.SysUser
	if err := dao.DbFirstById(&user, queryId); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONWrite(gin.H{"data": user, "roleIds": user.RoleIDs}, c)
}

// AuthRoleHandler
func (User) AuthRoleHandler(c *gin.Context) {
	id := gctx.ParamUInt(c, "id")
	var user model.SysUser
	if err := dao.DbFirstById(&user, id); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	t := middleware.GetUserToken(c)
	var roles []model.SysRole
	dao.DbFindBy(&roles, "created_by like ?", t.UserName) // 获取当前用户创建的角色
	gctx.JSONWrite(gin.H{"roles": roles, "user": user}, c)
}

// AddHandler 新增用户
func (User) AddHandler(c *gin.Context) {
	var p model.SysUser
	//获取参数
	if err := c.ShouldBind(&p.SysUserOpt); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	p.CreatedBy = middleware.GetUserToken(c).UserName
	if err := service.SysUserCreate(&p); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

// AddPageHandler 新增界面
func (User) AddPageHandler(c *gin.Context) {
	// trees, err := buildRoleTree(c)
	// if err != nil {
	// 	gctx.JSONWriteError(err, c)
	// 	return
	// }
	// var posts []model.SysPost
	// if err := dao.DbFind(&posts); err != nil {
	// 	gctx.JSONWriteError(err, c)
	// 	return
	// }
	// gctx.JSONWriteData(gin.H{"roles": trees, "posts": posts}, c)
}

// ExportHandler 导出
func (User) ExportHandler(c *gin.Context) {
	// var users []model.SysUser
	// totalCount, err := dao.DbFindPage(param.PageNum, param.PageSize, param.Where(sysUser), &model.SysUser{}, &users)
	gctx.JSON(gctx.StatusError).WriteData(nil, c)
}

// ProfileHandler profile
func (User) ProfileHandler(c *gin.Context) {
	t := middleware.GetUserToken(c)
	var user model.SysUser
	if err := dao.DbFirstById(&user, t.UserID); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONWrite(gin.H{"data": user, "roleGroup": "", "postGroup": ""}, c)
}

type updatePwd struct {
	OldPassword string `fdao:"oldPassword" binding:"required,min=0,max=30"`
	NewPassword string `fdao:"newPassword" binding:"required,min=0,max=30"`
}

// ProfileUpdatePwdHandler 重置密码
func (User) ProfileUpdatePwdHandler(c *gin.Context) {
	var p updatePwd
	if err := c.ShouldBind(&p); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	t := middleware.GetUserToken(c)
	var data model.SysUser
	if err := dao.DbFirstById(&data, t.UserID); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	oldPassword := service.SysUserPassword(&data, p.OldPassword)
	if oldPassword != data.Password {
		gctx.JSONWriteError(errors.New("old password error"), c)
		return
	}
	newPassword := service.SysUserPassword(&data, p.NewPassword)
	if err := dao.DbUpdateColById(&data, data.ID, "password", newPassword); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

// UpdateHandler 修改
func (User) UpdateHandler(c *gin.Context) {
	var user model.SysUser
	if err := c.ShouldBind(&user.SysUserOpt); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	if user.UserName == model.SysUserName {
		user.RoleIDs = nil
	}
	if err := dao.DbUpdateModel(user); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

type resetPwd struct {
	UserID   uint   `json:"userId"`
	Password string `json:"password"`
}

// ResetPwdHandler 修改密码
func (User) ResetPwdHandler(c *gin.Context) {
	var p resetPwd
	if err := c.ShouldBind(&p); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	var data model.SysUser
	if err := dao.DbFirstById(&data, p.UserID); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	password := service.SysUserPassword(&data, p.Password)
	if err := dao.DbUpdateColById(&model.SysUser{}, p.UserID, "password", password); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

// DeleteHandler 删除
func (User) DeleteHandler(c *gin.Context) {
	idstr := c.Param("id")
	if idstr != "" {
		ids := util.StringToIntSlice(idstr, ",")
		for i, v := range ids {
			if v == 1 {
				ids[i] = 0
				break
			}
		}
		if err := dao.DbDeleteByIds(&model.SysUser{}, ids); err != nil {
			gctx.JSONWriteError(err, c)
			return
		}
	}
	gctx.JSONOK(c)
}

// EnableHandler 改变状态
func (User) EnableHandler(c *gin.Context) {
	var p model.SysUser
	if err := c.ShouldBind(&p); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	if err := dao.DbUpdateColById(&p, p.ID, "status", p.Status); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

// UpdatePwdHandler 重置密码
func (User) UpdatePwdHandler(c *gin.Context) {
	var param updatePwd
	if err := c.ShouldBind(&param); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	t := middleware.GetUserToken(c)
	var data model.SysUser
	if err := dao.DbFirstById(&data, t.UserID); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	oldPassword := service.SysUserPassword(&data, param.OldPassword)
	if oldPassword != data.Password {
		gctx.JSONWriteError(errors.New("old password error"), c)
		return
	}
	newPassword := service.SysUserPassword(&data, param.NewPassword)
	if err := dao.DbUpdateColById(&data, data.ID, "password", newPassword); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

// ProfileAuatarHandler 上传头像
func (User) ProfileAuatarHandler(c *gin.Context) {
	t := middleware.GetUserToken(c)
	saveDir := configs.Public.Abs("upload")
	fileHead, err := c.FormFile("avatarfile")
	if err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	curdate := time.Now().UnixNano()
	filename := t.UserName + strconv.FormatInt(curdate, 10) + ".png"
	avatarURL := saveDir + filename
	if err := c.SaveUploadedFile(fileHead, avatarURL); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	if err := dao.DbUpdateColById(&model.SysUser{}, t.UserID, "avatar", avatarURL); err != nil {
		gctx.JSONWriteError(err, c)
		return
	}
	gctx.JSONOK(c)
}

func (o User) Router(r *gin.RouterGroup) {
	r.GET("/list", o.ListHandler)
	r.GET("/menu", o.MenuHandler)
	r.GET("/params", o.ParamsHandler)
	r.GET("/:id", o.GetHandler)
	r.GET("/authRole/:id", o.AuthRoleHandler)
	r.POST("", o.AddHandler)
	r.GET("/export", o.ExportHandler)
	r.PUT("", o.UpdateHandler)
	r.PUT("/resetPwd", o.ResetPwdHandler)
	r.DELETE("/:id", o.DeleteHandler)
	r.PUT("/enable", o.EnableHandler)
	r.GET("/profile", o.ProfileHandler)
	r.PUT("/profile", o.UpdateHandler)
	r.PUT("/profile/updatePwd", o.UpdatePwdHandler)
	r.POST("/profile/avatar", o.ProfileAuatarHandler)
}
